#ifndef MODEL
#define MODEL



/* MySQL Connector/C++ specific headers */


#include <mysql++.h>


using namespace std;


class Model
{
	public:

		void test();
		map<string,boost::any>  findAll();
		vector<boost::any>  findAll2();
		map<string,boost::any>  find(string,string,string,string,string);
		map<string,boost::any> exec(string);
		void execNonQuery(string);
		string name;
		mysqlpp::Connection con;
		Model(){open();}
		~Model(){close();}
	private:

		void open();
		void close();
		void separator(ostream&, string);
};

map<string,boost::any>  Model::find(string type, string columns, string condition, string order, string limit){
	map<string,boost::any> rt;

	mysqlpp::Query query = con.query("select * from "+ name);
		if (mysqlpp::StoreQueryResult res = query.store()) {
			//get column
			vector<string> columns;
			for(int i=0;i<res.num_fields();i++)
			{
				string name=res.field_name(i);
				columns.push_back(name);
			}

			mysqlpp::StoreQueryResult::const_iterator it;
			int index=0;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;
				map<string,boost::any> r;
				for(int i=0;i<columns.size();i++)
				{
					string columnvalue;
					row[i].to_string(columnvalue);
					r[columns[i]]=columnvalue;
				}
				rt[StringProcessor::itoa(index)]=r;
				index++;
			}

		}


	return rt;
}

void  Model::execNonQuery(string sql){
	map<string,boost::any> rt;

	mysqlpp::Query query = con.query(sql);
	query.exec();
}

map<string,boost::any>  Model::exec(string sql){
	map<string,boost::any> rt;

	mysqlpp::Query query = con.query(sql);
		if (mysqlpp::StoreQueryResult res = query.store()) {
			//get column
			vector<string> columns;
			for(int i=0;i<res.num_fields();i++)
			{
				string name=res.field_name(i);
				columns.push_back(name);
			}

			mysqlpp::StoreQueryResult::const_iterator it;
			int index=0;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;
				map<string,boost::any> r;
				for(int i=0;i<columns.size();i++)
				{
					string columnvalue;
					row[i].to_string(columnvalue);
					r[columns[i]]=columnvalue;
				}
				rt[StringProcessor::itoa(index)]=r;
				index++;
			}

		}


	return rt;
}
vector<boost::any>  Model::findAll2(){
	vector<boost::any> rt;

	mysqlpp::Query query = con.query("select * from "+ name);
		if (mysqlpp::StoreQueryResult res = query.store()) {
			//get column
			vector<string> columns;
			for(int i=0;i<res.num_fields();i++)
			{
				string name=res.field_name(i);
				columns.push_back(name);
			}

			mysqlpp::StoreQueryResult::const_iterator it;
			int index=0;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;
				map<string,boost::any> r;
				for(int i=0;i<columns.size();i++)
				{
					string columnvalue;
					row[i].to_string(columnvalue);
					r[columns[i]]=columnvalue;
				}
				rt.push_back(r);
				index++;
			}

		}


	return rt;
}
map<string,boost::any>  Model::findAll(){
	map<string,boost::any> rt;

	mysqlpp::Query query = con.query("select * from "+ name);
		if (mysqlpp::StoreQueryResult res = query.store()) {
			//get column
			vector<string> columns;
			for(int i=0;i<res.num_fields();i++)
			{
				string name=res.field_name(i);
				columns.push_back(name);
			}

			mysqlpp::StoreQueryResult::const_iterator it;
			int index=0;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;
				map<string,boost::any> r;
				for(int i=0;i<columns.size();i++)
				{
					string columnvalue;
					row[i].to_string(columnvalue);
					r[columns[i]]=columnvalue;
				}
				rt[StringProcessor::itoa(index)]=r;
				index++;
			}

		}


	return rt;
}

void Model::open(){
	try {
		mysqlpp::Connection co(false);
		con=co;
			//read from config
			// Connect to server, then dump a bunch of stuff we find on it
			con.connect(Configuration::getConfig("db").c_str(),Configuration::getConfig("host").c_str(),Configuration::getConfig("user").c_str(),Configuration::getConfig("pass").c_str());
			string conerr=con.error();
			if(conerr.size()>0)throw con.error();

		}
		catch (const mysqlpp::BadQuery& er) {
			// Handle any query errors
			string err=er.what();
			throw "Query error: " + err;
		}
		catch (const mysqlpp::Exception& er) {
				// Catch-all for any other MySQL++ exceptions
			string err=er.what();
			throw "Error: " + err;

		}

}

void Model::close(){
	con.disconnect();
}

#endif
